<!DOCTYPE html>
<html>
  <head>
  <meta http-equiv="content-type" content="text/html; charset=utf-8">
  <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport">
  <meta name="description" content="刘清政">
  <meta name="keyword" content="hexo-theme">
  
    <link rel="shortcut icon" href="/css/images/logo.png">
  
  <title>
    
      python/Django框架/16-Django高级之-中间件 | Justin-刘清政的博客
    
  </title>
  <link href="//cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
  <link href="//cdnjs.cloudflare.com/ajax/libs/nprogress/0.2.0/nprogress.min.css" rel="stylesheet">
  <link href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/tomorrow.min.css" rel="stylesheet">
  
<link rel="stylesheet" href="/css/style.css">

  
    
<link rel="stylesheet" href="/css/plugins/gitment.css">

  
  <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
  <script src="//cdnjs.cloudflare.com/ajax/libs/geopattern/1.2.3/js/geopattern.min.js"></script>
  <script src="//cdnjs.cloudflare.com/ajax/libs/nprogress/0.2.0/nprogress.min.js"></script>
  
    
<script src="/js/qrious.js"></script>

  
  
    
<script src="/js/gitment.js"></script>

  
  

  
<meta name="generator" content="Hexo 4.2.0"></head>
<div class="wechat-share">
  <img src="/css/images/logo.png" />
</div>

  <body>
    <header class="header fixed-header">
  <div class="header-container">
    <a class="home-link" href="/">
      <div class="logo"></div>
      <span>Justin-刘清政的博客</span>
    </a>
    <ul class="right-list">
      
        <li class="list-item">
          
            <a href="/" class="item-link">主页</a>
          
        </li>
      
        <li class="list-item">
          
            <a href="/tags/" class="item-link">标签</a>
          
        </li>
      
        <li class="list-item">
          
            <a href="/archives/" class="item-link">归档</a>
          
        </li>
      
        <li class="list-item">
          
            <a href="/about/" class="item-link">关于我</a>
          
        </li>
      
    </ul>
    <div class="menu">
      <span class="icon-bar"></span>
      <span class="icon-bar"></span>
      <span class="icon-bar"></span>
    </div>
    <div class="menu-mask">
      <ul class="menu-list">
        
          <li class="menu-item">
            
              <a href="/" class="menu-link">主页</a>
            
          </li>
        
          <li class="menu-item">
            
              <a href="/tags/" class="menu-link">标签</a>
            
          </li>
        
          <li class="menu-item">
            
              <a href="/archives/" class="menu-link">归档</a>
            
          </li>
        
          <li class="menu-item">
            
              <a href="/about/" class="menu-link">关于我</a>
            
          </li>
        
      </ul>
    </div>
  </div>
</header>

    <div id="article-banner">
  <h2>python/Django框架/16-Django高级之-中间件</h2>



  <p class="post-date">2020-09-24</p>
    <!-- 不蒜子统计 -->
    <span id="busuanzi_container_page_pv" style='display:none' class="">
        <i class="icon-smile icon"></i> 阅读数：<span id="busuanzi_value_page_pv"></span>次
    </span>
  <div class="arrow-down">
    <a href="javascript:;"></a>
  </div>
</div>
<main class="app-body flex-box">
  <!-- Article START -->
  <article class="post-article">
    <section class="markdown-content"><h2 id="一-什么是中间件"><a href="#一-什么是中间件" class="headerlink" title="一 什么是中间件"></a>一 什么是中间件</h2><p>中间件顾名思义，是<strong>介于request与response处理之间的一道处理过程</strong>，相对比较轻量级，并且在全局上改变django的输入与输出。因为改变的是全局，所以需要谨慎实用，用不好会影响到性能</p>
<p>Django中间件的定义：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Middleware is a framework of hooks into Django’s request&#x2F;response processing. </span><br><span class="line">It’s a light, low-level “plugin” system for globally altering Django’s input or output.</span><br></pre></td></tr></table></figure>

<h2 id="二-中间件有什么用"><a href="#二-中间件有什么用" class="headerlink" title="二 中间件有什么用"></a>二 中间件有什么用</h2><p>如果你想修改请求，例如被传送到view中的<strong>HttpRequest</strong>对象。 或者你想修改view返回的<strong>HttpResponse</strong>对象，这些都可以通过中间件来实现。</p>
<p>可能你还想在view执行之前做一些操作，这种情况就可以用 middleware来实现。</p>
<p>Django默认的中间件：（在django项目的settings模块中，有一个 MIDDLEWARE_CLASSES 变量，其中每一个元素就是一个中间件，如下图）</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">MIDDLEWARE &#x3D; [</span><br><span class="line">    &#39;django.middleware.security.SecurityMiddleware&#39;,</span><br><span class="line">    &#39;django.contrib.sessions.middleware.SessionMiddleware&#39;,</span><br><span class="line">    &#39;django.middleware.common.CommonMiddleware&#39;,</span><br><span class="line">    &#39;django.middleware.csrf.CsrfViewMiddleware&#39;,</span><br><span class="line">    &#39;django.contrib.auth.middleware.AuthenticationMiddleware&#39;,</span><br><span class="line">    &#39;django.contrib.messages.middleware.MessageMiddleware&#39;,</span><br><span class="line">    &#39;django.middleware.clickjacking.XFrameOptionsMiddleware&#39;,</span><br><span class="line">]</span><br></pre></td></tr></table></figure>

<p>每一个中间件都有具体的功能</p>
<h2 id="三-自定义中间件"><a href="#三-自定义中间件" class="headerlink" title="三 自定义中间件"></a>三 自定义中间件</h2><p> 中间件中主要有几个方法：</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">process_request(self,request)</span><br><span class="line"></span><br><span class="line">process_view(self, request, callback, callback_args, callback_kwargs)</span><br><span class="line"></span><br><span class="line">process_template_response(self,request,response)</span><br><span class="line"></span><br><span class="line">process_exception(self, request, exception)</span><br><span class="line"></span><br><span class="line">process_response(self, request, response)</span><br></pre></td></tr></table></figure>

<h3 id="process-request和process-response"><a href="#process-request和process-response" class="headerlink" title="process_request和process_response"></a>process_request和process_response</h3><p>当用户发起请求的时候会依次经过所有的的中间件，这个时候的请求时process_request,最后到达views的函数中，views函数处理后，在依次穿过中间件，这个时候是process_response,最后返回给请求者。</p>
<img src="https://tva1.sinaimg.cn/large/007S8ZIlgy1gj6ropdwwmj31xw0tik2x.jpg" alt="image-20200928231009962" style="zoom:50%;" />

<p>上述截图中的中间件都是django中的，我们也可以自己定义一个中间件，我们可以自己写一个类，<strong>但是必须继承MiddlewareMixin</strong></p>
<p>第一步：导入</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> django.utils.deprecation <span class="keyword">import</span> MiddlewareMixin</span><br></pre></td></tr></table></figure>

<p>第二步：自定义中间件 </p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> django.utils.deprecation <span class="keyword">import</span> MiddlewareMixin</span><br><span class="line"><span class="keyword">from</span> django.shortcuts <span class="keyword">import</span> HttpResponse</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Md1</span><span class="params">(MiddlewareMixin)</span>:</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">process_request</span><span class="params">(self,request)</span>:</span></span><br><span class="line">        print(<span class="string">"Md1请求"</span>)</span><br><span class="line"> </span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">process_response</span><span class="params">(self,request,response)</span>:</span></span><br><span class="line">        print(<span class="string">"Md1返回"</span>)</span><br><span class="line">        <span class="keyword">return</span> response</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Md2</span><span class="params">(MiddlewareMixin)</span>:</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">process_request</span><span class="params">(self,request)</span>:</span></span><br><span class="line">        print(<span class="string">"Md2请求"</span>)</span><br><span class="line">        <span class="comment">#return HttpResponse("Md2中断")</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">process_response</span><span class="params">(self,request,response)</span>:</span></span><br><span class="line">        print(<span class="string">"Md2返回"</span>)</span><br><span class="line">        <span class="keyword">return</span> response</span><br></pre></td></tr></table></figure>

<p>第三步：在view中定义一个视图函数（index）</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">index</span><span class="params">(request)</span>:</span></span><br><span class="line"></span><br><span class="line">    print(<span class="string">"view函数..."</span>)</span><br><span class="line">    <span class="keyword">return</span> HttpResponse(<span class="string">"OK"</span>)</span><br></pre></td></tr></table></figure>

<p>第四步：在settings.py的MIDDLEWARE里注册自己定义的中间件</p>
<img src="https://tva1.sinaimg.cn/large/007S8ZIlgy1gj6rppmohfj31y60ju7f2.jpg" alt="image-20200928231109972" style="zoom: 50%;" />

<p><strong>结果：</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">Md1请求</span><br><span class="line">Md2请求</span><br><span class="line">view函数...</span><br><span class="line">Md2返回</span><br><span class="line">Md1返回</span><br></pre></td></tr></table></figure>

<p><strong>注意：</strong>如果当请求到达请求2的时候直接不符合条件返回，即return HttpResponse(“Md2中断”)，程序将把请求直接发给中间件2返回，然后依次返回到请求者，结果如下：</p>
<p>返回Md2中断的页面，后台打印如下：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">Md1请求</span><br><span class="line">Md2请求</span><br><span class="line">Md2返回</span><br><span class="line">Md1返回</span><br></pre></td></tr></table></figure>

<p><strong>流程图如下：</strong></p>
<img src="https://tva1.sinaimg.cn/large/007S8ZIlgy1gj6rq9kng6j30ok0h6abw.jpg" alt="image-20200928231143055" style="zoom:50%;" />

<p>由此总结一下：</p>
<ol>
<li>中间件的process_request方法是在执行视图函数之前执行的。</li>
<li>当配置多个中间件时，会按照MIDDLEWARE中的注册顺序，也就是列表的索引值，从前到后依次执行的。</li>
<li>不同中间件之间传递的request都是同一个对象</li>
</ol>
<p>多个中间件中的process_response方法是按照MIDDLEWARE中的注册顺序<strong>倒序</strong>执行的，也就是说第一个中间件的process_request方法首先执行，而它的process_response方法最后执行，最后一个中间件的process_request方法最后一个执行，它的process_response方法是最先执行。</p>
<h3 id="process-view"><a href="#process-view" class="headerlink" title="process_view"></a>process_view</h3><p>process_view(self, request, view_func, view_args, view_kwargs)</p>
<p>该方法有四个参数</p>
<p>request是HttpRequest对象。</p>
<p>view_func是Django即将使用的视图函数。 （它是实际的函数对象，而不是函数的名称作为字符串。）</p>
<p>view_args是将传递给视图的位置参数的列表.</p>
<p>view_kwargs是将传递给视图的关键字参数的字典。 view_args和view_kwargs都不包含第一个视图参数（request）。</p>
<p>Django会在调用视图函数之前调用process_view方法。</p>
<p>它应该返回None或一个HttpResponse对象。  如果返回None，Django将继续处理这个请求，执行任何其他中间件的process_view方法，然后在执行相应的视图。  如果它返回一个HttpResponse对象，Django不会调用适当的视图函数。  它将执行中间件的process_response方法并将应用到该HttpResponse并返回结果。</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">process_view(self, request, callback, callback_args, callback_kwargs)</span><br></pre></td></tr></table></figure>

<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> django.utils.deprecation <span class="keyword">import</span> MiddlewareMixin</span><br><span class="line"><span class="keyword">from</span> django.shortcuts <span class="keyword">import</span> HttpResponse</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Md1</span><span class="params">(MiddlewareMixin)</span>:</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">process_request</span><span class="params">(self,request)</span>:</span></span><br><span class="line">        print(<span class="string">"Md1请求"</span>)</span><br><span class="line">        <span class="comment">#return HttpResponse("Md1中断")</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">process_response</span><span class="params">(self,request,response)</span>:</span></span><br><span class="line">        print(<span class="string">"Md1返回"</span>)</span><br><span class="line">        <span class="keyword">return</span> response</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">process_view</span><span class="params">(self, request, callback, callback_args, callback_kwargs)</span>:</span></span><br><span class="line">        print(<span class="string">"Md1view"</span>)</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Md2</span><span class="params">(MiddlewareMixin)</span>:</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">process_request</span><span class="params">(self,request)</span>:</span></span><br><span class="line">        print(<span class="string">"Md2请求"</span>)</span><br><span class="line">        <span class="keyword">return</span> HttpResponse(<span class="string">"Md2中断"</span>)</span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">process_response</span><span class="params">(self,request,response)</span>:</span></span><br><span class="line">        print(<span class="string">"Md2返回"</span>)</span><br><span class="line">        <span class="keyword">return</span> response</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">process_view</span><span class="params">(self, request, callback, callback_args, callback_kwargs)</span>:</span></span><br><span class="line">        print(<span class="string">"Md2view"</span>)</span><br></pre></td></tr></table></figure>

<p>结果如下：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">Md1请求</span><br><span class="line">Md2请求</span><br><span class="line">Md1view</span><br><span class="line">Md2view</span><br><span class="line">view函数...</span><br><span class="line">Md2返回</span><br><span class="line">Md1返回</span><br></pre></td></tr></table></figure>

<p>下图进行分析上面的过程：</p>
<img src="https://tva1.sinaimg.cn/large/007S8ZIlgy1gj6rrfsqhij30ns0k640l.jpg" alt="image-20200928231250612" style="zoom:50%;" />

<p>当最后一个中间的process_request到达路由关系映射之后，返回到中间件1的process_view，然后依次往下，到达views函数，最后通过process_response依次返回到达用户。</p>
<p>process_view可以用来调用视图函数：</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Md1</span><span class="params">(MiddlewareMixin)</span>:</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">process_request</span><span class="params">(self,request)</span>:</span></span><br><span class="line">        print(<span class="string">"Md1请求"</span>)</span><br><span class="line">        <span class="comment">#return HttpResponse("Md1中断")</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">process_response</span><span class="params">(self,request,response)</span>:</span></span><br><span class="line">        print(<span class="string">"Md1返回"</span>)</span><br><span class="line">        <span class="keyword">return</span> response</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">process_view</span><span class="params">(self, request, callback, callback_args, callback_kwargs)</span>:</span></span><br><span class="line"></span><br><span class="line">        <span class="comment"># return HttpResponse("hello")</span></span><br><span class="line"></span><br><span class="line">        response=callback(request,*callback_args,**callback_kwargs)</span><br><span class="line">        <span class="keyword">return</span> response</span><br></pre></td></tr></table></figure>

<p>结果如下：</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">Md1请求</span><br><span class="line">Md2请求</span><br><span class="line">view函数...</span><br><span class="line">Md2返回</span><br><span class="line">Md1返回</span><br></pre></td></tr></table></figure>

<p>注意：process_view如果有返回值，会越过其他的process_view以及视图函数，但是所有的process_response都还会执行。</p>
<h3 id="process-exception"><a href="#process-exception" class="headerlink" title="process_exception"></a>process_exception</h3><p>process_exception(self, request, exception)</p>
<p>该方法两个参数:</p>
<p>一个HttpRequest对象</p>
<p>一个exception是视图函数异常产生的Exception对象。</p>
<p>这个方法只有在视图函数中出现异常了才执行，它返回的值可以是一个None也可以是一个HttpResponse对象。如果是HttpResponse对象，Django将调用模板和中间件中的process_response方法，并返回给浏览器，否则将默认处理异常。如果返回一个None，则交给下一个中间件的process_exception方法来处理异常。它的执行顺序也是按照中间件注册顺序的倒序执行。</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">process_exception(self, request, exception)</span><br></pre></td></tr></table></figure>

<p>示例修改如下：</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Md1</span><span class="params">(MiddlewareMixin)</span>:</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">process_request</span><span class="params">(self,request)</span>:</span></span><br><span class="line">        print(<span class="string">"Md1请求"</span>)</span><br><span class="line">        <span class="comment">#return HttpResponse("Md1中断")</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">process_response</span><span class="params">(self,request,response)</span>:</span></span><br><span class="line">        print(<span class="string">"Md1返回"</span>)</span><br><span class="line">        <span class="keyword">return</span> response</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">process_view</span><span class="params">(self, request, callback, callback_args, callback_kwargs)</span>:</span></span><br><span class="line"></span><br><span class="line">        <span class="comment"># return HttpResponse("hello")</span></span><br><span class="line"></span><br><span class="line">        <span class="comment"># response=callback(request,*callback_args,**callback_kwargs)</span></span><br><span class="line">        <span class="comment"># return response</span></span><br><span class="line">        print(<span class="string">"md1 process_view..."</span>)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">process_exception</span><span class="params">(self,request,exception)</span>:</span></span><br><span class="line">        print(<span class="string">"md1 process_exception..."</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Md2</span><span class="params">(MiddlewareMixin)</span>:</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">process_request</span><span class="params">(self,request)</span>:</span></span><br><span class="line">        print(<span class="string">"Md2请求"</span>)</span><br><span class="line">        <span class="comment"># return HttpResponse("Md2中断")</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">process_response</span><span class="params">(self,request,response)</span>:</span></span><br><span class="line">        print(<span class="string">"Md2返回"</span>)</span><br><span class="line">        <span class="keyword">return</span> response</span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">process_view</span><span class="params">(self, request, callback, callback_args, callback_kwargs)</span>:</span></span><br><span class="line">        print(<span class="string">"md2 process_view..."</span>)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">process_exception</span><span class="params">(self,request,exception)</span>:</span></span><br><span class="line">        print(<span class="string">"md1 process_exception..."</span>)</span><br></pre></td></tr></table></figure>

<p>结果如下：</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">Md1请求</span><br><span class="line">Md2请求</span><br><span class="line">md1 process_view...</span><br><span class="line">md2 process_view...</span><br><span class="line">view函数...</span><br><span class="line"></span><br><span class="line">Md2返回</span><br><span class="line">Md1返回</span><br></pre></td></tr></table></figure>

<p>流程图如下：</p>
<p>当views出现错误时：</p>
<img src="https://tva1.sinaimg.cn/large/007S8ZIlgy1gj6rt8vwvjj30ue0k2wh6.jpg" alt="image-20200928231435070" style="zoom:50%;" />

<p> 将md2的process_exception修改如下：</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">process_exception</span><span class="params">(self,request,exception)</span>:</span></span><br><span class="line"></span><br><span class="line">      print(<span class="string">"md2 process_exception..."</span>)</span><br><span class="line">      <span class="keyword">return</span> HttpResponse(<span class="string">"error"</span>)</span><br></pre></td></tr></table></figure>

<p>结果如下：</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">Md1请求</span><br><span class="line">Md2请求</span><br><span class="line">md1 process_view...</span><br><span class="line">md2 process_view...</span><br><span class="line">view函数...</span><br><span class="line">md2 process_exception...</span><br><span class="line">Md2返回</span><br><span class="line">Md1返回</span><br></pre></td></tr></table></figure>

<h3 id="process-template-response-self-request-response"><a href="#process-template-response-self-request-response" class="headerlink" title="process_template_response(self,request,response)"></a>process_template_response(self,request,response)</h3><p>该方法对视图函数返回值有要求，必须是一个含有render方法类的对象，才会执行此方法</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Test</span>:</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self,status,msg)</span>:</span></span><br><span class="line">        self.status=status</span><br><span class="line">        self.msg=msg</span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">render</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">import</span> json</span><br><span class="line">        dic=&#123;<span class="string">'status'</span>:self.status,<span class="string">'msg'</span>:self.msg&#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> HttpResponse(json.dumps(dic))</span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">index</span><span class="params">(response)</span>:</span></span><br><span class="line">    <span class="keyword">return</span> Test(<span class="literal">True</span>,<span class="string">'测试'</span>)</span><br></pre></td></tr></table></figure>

<h2 id="四-中间件应用场景"><a href="#四-中间件应用场景" class="headerlink" title="四 中间件应用场景"></a>四 中间件应用场景</h2><h3 id="1、做IP访问频率限制"><a href="#1、做IP访问频率限制" class="headerlink" title="1、做IP访问频率限制"></a><strong>1、做IP访问频率限制</strong></h3><p>某些IP访问服务器的频率过高，进行拦截，比如限制每分钟不能超过20次。</p>
<h3 id="2、URL访问过滤"><a href="#2、URL访问过滤" class="headerlink" title="2、URL访问过滤"></a><strong>2、URL访问过滤</strong></h3><p>如果用户访问的是login视图（放过）</p>
<p>如果访问其他视图，需要检测是不是有session认证，已经有了放行，没有返回login，这样就省得在多个视图函数上写装饰器了！</p>
<p>作为延伸扩展内容，有余力的同学可以尝试着读一下以下两个自带的中间件：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&#39;django.contrib.sessions.middleware.SessionMiddleware&#39;,</span><br><span class="line">&#39;django.contrib.auth.middleware.AuthenticationMiddleware&#39;,</span><br></pre></td></tr></table></figure>

<h2 id="五-CSRF-TOKEN跨站请求伪造"><a href="#五-CSRF-TOKEN跨站请求伪造" class="headerlink" title="五 CSRF_TOKEN跨站请求伪造"></a>五 CSRF_TOKEN跨站请求伪造</h2><p>介绍：<a href="https://www.cnblogs.com/liuqingzheng/p/9505044.html" target="_blank" rel="noopener">浅谈CSRF（Cross-site request forgery）跨站请求伪造</a></p>
<h3 id="在form表单中应用："><a href="#在form表单中应用：" class="headerlink" title="在form表单中应用："></a>在form表单中应用：</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&lt;form action&#x3D;&quot;&quot; method&#x3D;&quot;post&quot;&gt;</span><br><span class="line">    &#123;% csrf_token %&#125;</span><br><span class="line">    &lt;p&gt;用户名：&lt;input type&#x3D;&quot;text&quot; name&#x3D;&quot;name&quot;&gt;&lt;&#x2F;p&gt;</span><br><span class="line">    &lt;p&gt;密码：&lt;input type&#x3D;&quot;text&quot; name&#x3D;&quot;password&quot;&gt;&lt;&#x2F;p&gt;</span><br><span class="line">    &lt;p&gt;&lt;input type&#x3D;&quot;submit&quot;&gt;&lt;&#x2F;p&gt;</span><br><span class="line">&lt;&#x2F;form&gt;</span><br></pre></td></tr></table></figure>

<h3 id="在Ajax中应用："><a href="#在Ajax中应用：" class="headerlink" title="在Ajax中应用："></a>在Ajax中应用：</h3><h4 id="放在data里："><a href="#放在data里：" class="headerlink" title="放在data里："></a>放在data里：</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line">&lt;!DOCTYPE html&gt;</span><br><span class="line">&lt;html lang&#x3D;&quot;en&quot;&gt;</span><br><span class="line">&lt;head&gt;</span><br><span class="line">    &lt;meta charset&#x3D;&quot;UTF-8&quot;&gt;</span><br><span class="line">    &lt;script src&#x3D;&quot;&#x2F;static&#x2F;jquery-3.3.1.js&quot;&gt;&lt;&#x2F;script&gt;</span><br><span class="line">    &lt;title&gt;Title&lt;&#x2F;title&gt;</span><br><span class="line">&lt;&#x2F;head&gt;</span><br><span class="line">&lt;body&gt;</span><br><span class="line">&lt;form action&#x3D;&quot;&quot; method&#x3D;&quot;post&quot;&gt;</span><br><span class="line">    &#123;% csrf_token %&#125;</span><br><span class="line">    &lt;p&gt;用户名：&lt;input type&#x3D;&quot;text&quot; name&#x3D;&quot;name&quot;&gt;&lt;&#x2F;p&gt;</span><br><span class="line">    &lt;p&gt;密码：&lt;input type&#x3D;&quot;text&quot; name&#x3D;&quot;password&quot; id&#x3D;&quot;pwd&quot;&gt;&lt;&#x2F;p&gt;</span><br><span class="line">    &lt;p&gt;&lt;input type&#x3D;&quot;submit&quot;&gt;&lt;&#x2F;p&gt;</span><br><span class="line">&lt;&#x2F;form&gt;</span><br><span class="line">&lt;button class&#x3D;&quot;btn&quot;&gt;点我&lt;&#x2F;button&gt;</span><br><span class="line">&lt;&#x2F;body&gt;</span><br><span class="line">&lt;script&gt;</span><br><span class="line">    $(&quot;.btn&quot;).click(function () &#123;</span><br><span class="line">        $.ajax(&#123;</span><br><span class="line">            url: &#39;&#39;,</span><br><span class="line">            type: &#39;post&#39;,</span><br><span class="line">            data: &#123;</span><br><span class="line">                &#39;name&#39;: $(&#39;[name&#x3D;&quot;name&quot;]&#39;).val(),</span><br><span class="line">                &#39;password&#39;: $(&quot;#pwd&quot;).val(),</span><br><span class="line">                &#39;csrfmiddlewaretoken&#39;: $(&#39;[name&#x3D;&quot;csrfmiddlewaretoken&quot;]&#39;).val()</span><br><span class="line">            &#125;,</span><br><span class="line">            success: function (data) &#123;</span><br><span class="line">                console.log(data)</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">        &#125;)</span><br><span class="line">    &#125;)</span><br><span class="line">&lt;&#x2F;script&gt;</span><br><span class="line">&lt;&#x2F;html&gt;</span><br></pre></td></tr></table></figure>

<h4 id="放在cookie里："><a href="#放在cookie里：" class="headerlink" title="放在cookie里："></a>放在cookie里：</h4><p>获取cookie：document.cookie</p>
<p>是一个字符串，可以自己用js切割，也可以用jquery的插件</p>
<p>获取cookie：$.cookie(‘csrftoken’)</p>
<p>设置cookie：$.cookie(‘key’,’value’)</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">"en"</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"UTF-8"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">"/static/jquery-3.3.1.js"</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">"/static/jquery.cookie.js"</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>Title<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">form</span> <span class="attr">action</span>=<span class="string">""</span> <span class="attr">method</span>=<span class="string">"post"</span>&gt;</span></span><br><span class="line">    &#123;% csrf_token %&#125;</span><br><span class="line">    <span class="tag">&lt;<span class="name">p</span>&gt;</span>用户名：<span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">"text"</span> <span class="attr">name</span>=<span class="string">"name"</span>&gt;</span><span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">p</span>&gt;</span>密码：<span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">"text"</span> <span class="attr">name</span>=<span class="string">"password"</span> <span class="attr">id</span>=<span class="string">"pwd"</span>&gt;</span><span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">p</span>&gt;</span><span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">"submit"</span>&gt;</span><span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">form</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">button</span> <span class="attr">class</span>=<span class="string">"btn"</span>&gt;</span>点我<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="javascript">    $(<span class="string">".btn"</span>).click(<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span></span><br><span class="line"><span class="javascript">        <span class="keyword">var</span> token=$.cookie(<span class="string">'csrftoken'</span>)</span></span><br><span class="line"><span class="actionscript">        <span class="comment">//var token='&#123;&#123; csrf_token &#125;&#125;'</span></span></span><br><span class="line"><span class="javascript">        $.ajax(&#123;</span></span><br><span class="line"><span class="actionscript">            url: <span class="string">''</span>,</span></span><br><span class="line"><span class="actionscript">            headers:&#123;<span class="string">'X-CSRFToken'</span>:token&#125;,</span></span><br><span class="line"><span class="actionscript">            type: <span class="string">'post'</span>,</span></span><br><span class="line">            data: &#123;</span><br><span class="line"><span class="javascript">                <span class="string">'name'</span>: $(<span class="string">'[name="name"]'</span>).val(),</span></span><br><span class="line"><span class="javascript">                <span class="string">'password'</span>: $(<span class="string">"#pwd"</span>).val(),</span></span><br><span class="line">            &#125;,</span><br><span class="line"><span class="actionscript">            success: <span class="function"><span class="keyword">function</span> <span class="params">(data)</span> </span>&#123;</span></span><br><span class="line"><span class="javascript">                <span class="built_in">console</span>.log(data)</span></span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">        &#125;)</span><br><span class="line">    &#125;)</span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h3 id="其它操作"><a href="#其它操作" class="headerlink" title="其它操作"></a>其它操作</h3><p>全站禁用：注释掉中间件 <strong>‘django.middleware.csrf.CsrfViewMiddleware’,</strong></p>
<p>局部禁用：用装饰器（在FBV中使用）</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> django.views.decorators.csrf <span class="keyword">import</span> csrf_exempt,csrf_protect</span><br><span class="line"><span class="comment"># 不再检测，局部禁用（前提是全站使用）</span></span><br><span class="line"><span class="comment"># @csrf_exempt</span></span><br><span class="line"><span class="comment"># 检测，局部使用（前提是全站禁用）</span></span><br><span class="line"><span class="comment"># @csrf_protect</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">csrf_token</span><span class="params">(request)</span>:</span></span><br><span class="line">    <span class="keyword">if</span> request.method==<span class="string">'POST'</span>:</span><br><span class="line">        print(request.POST)</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> HttpResponse(<span class="string">'ok'</span>)</span><br><span class="line">    <span class="keyword">return</span> render(request,<span class="string">'csrf_token.html'</span>)</span><br></pre></td></tr></table></figure>



<p>在CBV中使用：</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># CBV中使用</span></span><br><span class="line"><span class="keyword">from</span> django.views <span class="keyword">import</span> View</span><br><span class="line"><span class="keyword">from</span> django.views.decorators.csrf <span class="keyword">import</span> csrf_exempt,csrf_protect</span><br><span class="line"><span class="keyword">from</span> django.utils.decorators <span class="keyword">import</span> method_decorator</span><br><span class="line"><span class="comment"># CBV的csrf装饰器，只能加载类上（指定方法为dispatch）和dispatch方法上（django的bug）</span></span><br><span class="line"><span class="comment"># 给get方法使用csrf_token检测</span></span><br><span class="line"><span class="meta">@method_decorator(csrf_exempt,name='dispatch')</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Foo</span><span class="params">(View)</span>:</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get</span><span class="params">(self,request)</span>:</span></span><br><span class="line">        <span class="keyword">pass</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">post</span><span class="params">(self,request)</span>:</span></span><br><span class="line">        <span class="keyword">pass</span></span><br></pre></td></tr></table></figure></section>
    <!-- Tags START -->
    
    <!-- Tags END -->
    <!-- NAV START -->
    
  <div class="nav-container">
    <!-- reverse left and right to put prev and next in a more logic postition -->
    
      <a class="nav-left" href="/python/Django%E6%A1%86%E6%9E%B6/12-Django%E9%AB%98%E7%BA%A7%E4%B9%8B-Django%E4%B8%8EAjax/">
        <span class="nav-arrow">← </span>
        
          python/Django框架/12-Django高级之-Django与Ajax
        
      </a>
    
    
      <a class="nav-right" href="/python/Django%E6%A1%86%E6%9E%B6/5-%E8%B7%AF%E7%94%B1%E6%8E%A7%E5%88%B6/">
        
          python/Django框架/5-路由控制
        
        <span class="nav-arrow"> →</span>
      </a>
    
  </div>

    <!-- NAV END -->
    <!-- 打赏 START -->
    
      <div class="money-like">
        <div class="reward-btn">
          赏
          <span class="money-code">
            <span class="alipay-code">
              <div class="code-image"></div>
              <b>使用支付宝打赏</b>
            </span>
            <span class="wechat-code">
              <div class="code-image"></div>
              <b>使用微信打赏</b>
            </span>
          </span>
        </div>
        <p class="notice">点击上方按钮,请我喝杯咖啡！</p>
      </div>
    
    <!-- 打赏 END -->
    <!-- 二维码 START -->
    
      <div class="qrcode">
        <canvas id="share-qrcode"></canvas>
        <p class="notice">扫描二维码，分享此文章</p>
      </div>
    
    <!-- 二维码 END -->
    
      <!-- Gitment START -->
      <div id="comments"></div>
      <!-- Gitment END -->
    
  </article>
  <!-- Article END -->
  <!-- Catalog START -->
  
    <aside class="catalog-container">
  <div class="toc-main">
  <!-- 不蒜子统计 -->
    <strong class="toc-title">目录</strong>
    
      <ol class="toc-nav"><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#一-什么是中间件"><span class="toc-nav-text">一 什么是中间件</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#二-中间件有什么用"><span class="toc-nav-text">二 中间件有什么用</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#三-自定义中间件"><span class="toc-nav-text">三 自定义中间件</span></a><ol class="toc-nav-child"><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#process-request和process-response"><span class="toc-nav-text">process_request和process_response</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#process-view"><span class="toc-nav-text">process_view</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#process-exception"><span class="toc-nav-text">process_exception</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#process-template-response-self-request-response"><span class="toc-nav-text">process_template_response(self,request,response)</span></a></li></ol></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#四-中间件应用场景"><span class="toc-nav-text">四 中间件应用场景</span></a><ol class="toc-nav-child"><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#1、做IP访问频率限制"><span class="toc-nav-text">1、做IP访问频率限制</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#2、URL访问过滤"><span class="toc-nav-text">2、URL访问过滤</span></a></li></ol></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#五-CSRF-TOKEN跨站请求伪造"><span class="toc-nav-text">五 CSRF_TOKEN跨站请求伪造</span></a><ol class="toc-nav-child"><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#在form表单中应用："><span class="toc-nav-text">在form表单中应用：</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#在Ajax中应用："><span class="toc-nav-text">在Ajax中应用：</span></a><ol class="toc-nav-child"><li class="toc-nav-item toc-nav-level-4"><a class="toc-nav-link" href="#放在data里："><span class="toc-nav-text">放在data里：</span></a></li><li class="toc-nav-item toc-nav-level-4"><a class="toc-nav-link" href="#放在cookie里："><span class="toc-nav-text">放在cookie里：</span></a></li></ol></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#其它操作"><span class="toc-nav-text">其它操作</span></a></li></ol></li></ol>
    
  </div>
</aside>
  
  <!-- Catalog END -->
</main>

<script>
  (function () {
    var url = 'http://www.liuqingzheng.top/python/Django框架/16-Django高级之-中间件/';
    var banner = ''
    if (banner !== '' && banner !== 'undefined' && banner !== 'null') {
      $('#article-banner').css({
        'background-image': 'url(' + banner + ')'
      })
    } else {
      $('#article-banner').geopattern(url)
    }
    $('.header').removeClass('fixed-header')

    // error image
    $(".markdown-content img").on('error', function() {
      $(this).attr('src', 'http://file.muyutech.com/error-img.png')
      $(this).css({
        'cursor': 'default'
      })
    })

    // zoom image
    $(".markdown-content img").on('click', function() {
      var src = $(this).attr('src')
      if (src !== 'http://file.muyutech.com/error-img.png') {
        var imageW = $(this).width()
        var imageH = $(this).height()

        var zoom = ($(window).width() * 0.95 / imageW).toFixed(2)
        zoom = zoom < 1 ? 1 : zoom
        zoom = zoom > 2 ? 2 : zoom
        var transY = (($(window).height() - imageH) / 2).toFixed(2)

        $('body').append('<div class="image-view-wrap"><div class="image-view-inner"><img src="'+ src +'" /></div></div>')
        $('.image-view-wrap').addClass('wrap-active')
        $('.image-view-wrap img').css({
          'width': `${imageW}`,
          'transform': `translate3d(0, ${transY}px, 0) scale3d(${zoom}, ${zoom}, 1)`
        })
        $('html').css('overflow', 'hidden')

        $('.image-view-wrap').on('click', function() {
          $(this).remove()
          $('html').attr('style', '')
        })
      }
    })
  })();
</script>


  <script>
    var qr = new QRious({
      element: document.getElementById('share-qrcode'),
      value: document.location.href
    });
  </script>



  <script>
    var gitmentConfig = "liuqingzheng";
    if (gitmentConfig !== 'undefined') {
      var gitment = new Gitment({
        id: "python/Django框架/16-Django高级之-中间件",
        owner: "liuqingzheng",
        repo: "FuckBlog",
        oauth: {
          client_id: "32a4076431cf39d0ecea",
          client_secret: "94484bd79b3346a949acb2fda3c8a76ce16990c6"
        },
        theme: {
          render(state, instance) {
            const container = document.createElement('div')
            container.lang = "en-US"
            container.className = 'gitment-container gitment-root-container'
            container.appendChild(instance.renderHeader(state, instance))
            container.appendChild(instance.renderEditor(state, instance))
            container.appendChild(instance.renderComments(state, instance))
            container.appendChild(instance.renderFooter(state, instance))
            return container;
          }
        }
      })
      gitment.render(document.getElementById('comments'))
    }
  </script>




    <div class="scroll-top">
  <span class="arrow-icon"></span>
</div>
    <footer class="app-footer">
<!-- 不蒜子统计 -->
<span id="busuanzi_container_site_pv">
     本站总访问量<span id="busuanzi_value_site_pv"></span>次
</span>
<span class="post-meta-divider">|</span>
<span id="busuanzi_container_site_uv" style='display:none'>
     本站访客数<span id="busuanzi_value_site_uv"></span>人
</span>
<script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>



  <p class="copyright">
    &copy; 2021 | Proudly powered by <a href="https://www.cnblogs.com/xiaoyuanqujing" target="_blank">小猿取经</a>
    <br>
    Theme by <a href="https://www.cnblogs.com/xiaoyuanqujing" target="_blank" rel="noopener">小猿取经</a>
  </p>
</footer>

<script>
  function async(u, c) {
    var d = document, t = 'script',
      o = d.createElement(t),
      s = d.getElementsByTagName(t)[0];
    o.src = u;
    if (c) { o.addEventListener('load', function (e) { c(null, e); }, false); }
    s.parentNode.insertBefore(o, s);
  }
</script>
<script>
  async("//cdnjs.cloudflare.com/ajax/libs/fastclick/1.0.6/fastclick.min.js", function(){
    FastClick.attach(document.body);
  })
</script>

<script>
  var hasLine = 'true';
  async("//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js", function(){
    $('figure pre').each(function(i, block) {
      var figure = $(this).parents('figure');
      if (hasLine === 'false') {
        figure.find('.gutter').hide();
      }
      var lang = figure.attr('class').split(' ')[1] || 'code';
      var codeHtml = $(this).html();
      var codeTag = document.createElement('code');
      codeTag.className = lang;
      codeTag.innerHTML = codeHtml;
      $(this).attr('class', '').empty().html(codeTag);
      figure.attr('data-lang', lang.toUpperCase());
      hljs.highlightBlock(block);
    });
  })
</script>





<!-- Baidu Tongji -->

<script>
    var _baId = 'c5fd96eee1193585be191f318c3fa725';
    // Originial
    var _hmt = _hmt || [];
    (function() {
      var hm = document.createElement("script");
      hm.src = "//hm.baidu.com/hm.js?" + _baId;
      var s = document.getElementsByTagName("script")[0];
      s.parentNode.insertBefore(hm, s);
    })();
</script>


<script src="/js/script.js"></script>


<script src="/js/search.js"></script>


<script src="/js/load.js"></script>



  <span class="local-search local-search-google local-search-plugin" style="right: 50px;top: 70px;;position:absolute;z-index:2;">
      <input type="search" placeholder="站内搜索" id="local-search-input" class="local-search-input-cls" style="">
      <div id="local-search-result" class="local-search-result-cls"></div>
  </span>


  </body>
</html>